// 环形图片
import { useEffect, useRef } from 'react'
import * as THREE from 'three'
import './App.css'
import gsap from 'gsap'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

function App() {
  // 使用useRef来获取DOM元素引用
  const view1Ref = useRef(null);
  const view2Ref = useRef(null);
  const canvasRef = useRef(null);

  useEffect(() => {
    // 确保DOM元素已经渲染
    const view1Elem = view1Ref.current;
    const view2Elem = view2Ref.current;

    if (!view1Elem || !view2Elem) {
      console.error('DOM元素未找到');
      return;
    }

    // 场景
    const scene = new THREE.Scene()
    // 创建相机
    const camera = new THREE.PerspectiveCamera(
      50,//相机的角度
      window.innerWidth / window.innerHeight,//相机的宽高比
      0.1,//相机的近截面
      100//相机的远截面
    )
    camera.position.z = 13
    camera.position.y = 2
    camera.position.x = 0
    camera.lookAt(0, 2, 0)
    const cameraHelper = new THREE.CameraHelper(camera);
    scene.add(cameraHelper);

    //  定义第二个相机和控制器
    const camera2 = new THREE.PerspectiveCamera(
      60,  // fov
      2,   // aspect
      0.1, // near
      500, // far
    );
    camera2.position.set(40, 10, 30);
    camera2.lookAt(0, 5, 0);

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({ antialias: true })
    renderer.setSize(window.innerWidth, window.innerHeight)//设置渲染尺寸
    renderer.setPixelRatio(window.devicePixelRatio);

    // 将canvas添加到指定的容器中
    if (canvasRef.current) {
      canvasRef.current.appendChild(renderer.domElement);
    } else {
      document.body.appendChild(renderer.domElement);
    }

    // 获取canvas引用
    const canvas = renderer.domElement;

    // 检查渲染器是否需要调整大小的函数
    function resizeRendererToDisplaySize(renderer) {
      const canvas = renderer.domElement;
      const width = canvas.clientWidth;
      const height = canvas.clientHeight;
      const needResize = canvas.width !== width || canvas.height !== height;
      if (needResize) {
        renderer.setSize(width, height, false);
      }
      return needResize;
    }

    // 设置剪刀函数
    function setScissorForElement(elem) {
      const canvasRect = canvas.getBoundingClientRect();
      const elemRect = elem.getBoundingClientRect();

      // 计算canvas的尺寸
      const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
      const left = Math.max(0, elemRect.left - canvasRect.left);
      const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
      const top = Math.max(0, elemRect.top - canvasRect.top);

      const width = Math.min(canvasRect.width, right - left);
      const height = Math.min(canvasRect.height, bottom - top);

      // 设置剪函数以仅渲染一部分场景
      const positiveYUpBottom = canvasRect.height - bottom;
      renderer.setScissor(left, positiveYUpBottom, width, height);
      renderer.setViewport(left, positiveYUpBottom, width, height);

      // 返回aspect
      return width / height;
    }

    // --------------------------------main-----------------------------------------------
    // 创建一个场景图
    const baseObrit = new THREE.Object3D()
    baseObrit.position.set(0, 0, 0)

    scene.add(baseObrit)

    // 图片相关xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    const loader = new THREE.TextureLoader();
    const imageCount = 12;
    const radius = 10;
    const group = new THREE.Group();

    // 设置统一的最大尺寸，保持图片比例
    const maxSize = 3; // 最大边长

    for (let i = 0; i < imageCount; i++) {
      const imgPath = `/images/${i + 1}.jpg`; // 自动拼接路径

      // 使用回调函数处理纹理加载完成后的逻辑
      loader.load(imgPath, (texture) => {
        // 水平翻转纹理（如果需要的话）
        texture.wrapS = THREE.RepeatWrapping;
        texture.repeat.x = -1;

        // 获取图片的原始尺寸
        const image = texture.image;
        const imageWidth = image.width;
        const imageHeight = image.height;

        // 计算图片的宽高比
        const aspectRatio = imageWidth / imageHeight;

        // 根据宽高比计算平面的实际尺寸，保持最大边长不超过maxSize
        let planeWidth, planeHeight;
        if (aspectRatio > 1) {
          // 宽图：宽度为maxSize，高度按比例缩放
          planeWidth = maxSize;
          planeHeight = maxSize / aspectRatio;
        } else {
          // 高图：高度为maxSize，宽度按比例缩放
          planeHeight = maxSize;
          planeWidth = maxSize * aspectRatio;
        }

        // 创建材质，设置透明度
        const material = new THREE.MeshBasicMaterial({
          map: texture,
          side: THREE.DoubleSide,
          transparent: true, // 启用透明度
          alphaTest: 0.1 // 设置alpha测试值，低于此值的像素将被丢弃
        });

        // 使用计算出的尺寸创建平面几何体
        const plane = new THREE.Mesh(new THREE.PlaneGeometry(planeWidth, planeHeight), material);

        // 极坐标计算位置
        const angle = (i / imageCount) * Math.PI * 2;
        plane.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);
        plane.lookAt(0, 0, 0);

        // 将平面添加到组中
        group.add(plane);
      },
        // 加载进度回调（可选）
        undefined,
        // 加载错误回调
        (error) => {
          console.error(`加载图片 ${imgPath} 失败:`, error);
        });
    }

    // 设置组的位置
    group.position.set(0, 2, 0);
    baseObrit.add(group);

    // 添加地面xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    // 加载纹理
    const planeSize = 40;
    loader.load('./checker.png', (texture) => {
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      texture.magFilter = THREE.NearestFilter;
      texture.colorSpace = THREE.SRGBColorSpace;
      const repeats = planeSize / 2;
      texture.repeat.set(repeats, repeats);
      const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
      const planeMat = new THREE.MeshPhongMaterial({
        map: texture,
        side: THREE.DoubleSide,
      });
      const mesh = new THREE.Mesh(planeGeo, planeMat);
      mesh.rotation.x = Math.PI * -.5;
      scene.add(mesh);
    });

    // 光源相关xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    // 添加点光源
    const color = 0xFFFFFF;
    const intensity = 150;
    const light = new THREE.PointLight(color, intensity);
    light.position.set(0, 10, 0);
    scene.add(light);
    // 点光源辅助器
    const helper = new THREE.PointLightHelper(light);
    scene.add(helper);

    // 添加点击事件监听xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    let selectedMesh = null; // 当前选中的图片
    let originalPosition = null;
    let originalQuaternion = null;
    // 创建射线
    const raycaster = new THREE.Raycaster()
    // 鼠标位置
    const mouse = new THREE.Vector2()

    // 鼠标事件处理函数
    function handleMouseClick(e, targetCamera, targetView) {
      const viewRect = targetView.getBoundingClientRect();

      // 计算相对于视口的鼠标坐标
      mouse.x = ((e.clientX - viewRect.left) / viewRect.width) * 2 - 1;
      mouse.y = -((e.clientY - viewRect.top) / viewRect.height) * 2 + 1;

      raycaster.setFromCamera(mouse, targetCamera);
      const intersects = raycaster.intersectObjects(group.children);

      if (intersects.length > 0) {
        const mesh = intersects[0].object;

        if (!selectedMesh) {
          selectedMesh = mesh;

          // 记录原始位置和旋转
          originalPosition = mesh.position.clone();
          originalQuaternion = mesh.quaternion.clone();

          // 正确的方法：获取相机位置，然后沿着相机朝向向前移动指定距离
          const cameraPosition = targetCamera.position.clone();

          // 获取相机的朝向向量（相机看向的方向）
          const cameraDirection = new THREE.Vector3();
          targetCamera.getWorldDirection(cameraDirection);

          // 计算目标位置：相机位置 + 朝向向量 * 距离
          const distance = 10; // 距离相机8个单位
          const targetPos = cameraPosition.clone().add(cameraDirection.multiplyScalar(distance));

          // 让图片面向相机
          const lookAtDirection = cameraPosition.clone().sub(targetPos).normalize();
          const lookAtQuaternion = new THREE.Quaternion();
          const lookAtMatrix = new THREE.Matrix4();
          lookAtMatrix.lookAt(targetPos, cameraPosition, new THREE.Vector3(0, 1, 0));
          lookAtQuaternion.setFromRotationMatrix(lookAtMatrix);

          // 动画移动 mesh 到相机前方
          gsap.to(mesh.position, {
            x: targetPos.x,
            y: targetPos.y,
            z: targetPos.z,
            duration: 1,
            ease: "power2.out"
          });

          // 动画旋转 mesh 面向相机
          gsap.to(mesh.quaternion, {
            x: lookAtQuaternion.x,
            y: lookAtQuaternion.y,
            z: lookAtQuaternion.z,
            w: lookAtQuaternion.w,
            duration: 1,
            ease: "power2.out"
          });

        } else {
          // 如果已经选中，再次点击时恢复原位
          gsap.to(selectedMesh.position, {
            x: originalPosition.x,
            y: originalPosition.y,
            z: originalPosition.z,
            duration: 1,
            ease: "power2.out"
          });

          gsap.to(selectedMesh.quaternion, {
            x: originalQuaternion.x,
            y: originalQuaternion.y,
            z: originalQuaternion.z,
            w: originalQuaternion.w,
            duration: 1,
            ease: "power2.out"
          });

          selectedMesh = null;
        }
      }
    }

    // 为view1添加点击事件
    // view1Elem.addEventListener('click', (e) => {
    //   handleMouseClick(e, camera, view1Elem);
    // });

    // 为view2添加点击事件
    view2Elem.addEventListener('click', (e) => {
      handleMouseClick(e, camera2, view2Elem);
    });

    // --------------------------------bottom--------------------------------------------------------------------------------------------

    // 设置相机位置


    // 添加世界坐标辅助器
    const axesHelper = new THREE.AxesHelper(5)
    scene.add(axesHelper)

    // // 创建轨道控制器 - 确保在DOM元素存在后创建
    // const controls = new OrbitControls(camera, view1Elem);
    // // 阻尼
    // controls.enableDamping = true;
    // // 旋转
    // controls.enableRotate = true;
    // // 缩放
    // controls.enableZoom = true;
    // // 设置阻尼系数
    // controls.dampingFactor = 0.05;
    // // 设置控制器目标
    // controls.target.set(0, 3, 0);
    // controls.update();

    // 创建第二个轨道控制器
    const controls2 = new OrbitControls(camera2, view2Elem);
    controls2.enableDamping = true;
    controls2.enableRotate = true;
    controls2.enableZoom = true;
    controls2.dampingFactor = 0.05;
    controls2.target.set(0, 5, 0);
    controls2.update();

    // 双摄像机渲染函数
    function render() {
      // 检查渲染器是否需要调整大小
      if (resizeRendererToDisplaySize(renderer)) {
        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
      }

      // 启用剪刀函数
      renderer.setScissorTest(true);

      // 渲染主视野 (view1)
      {
        const aspect = setScissorForElement(view1Elem);

        // 用计算出的aspect修改摄像机参数
        camera.aspect = aspect;
        camera.updateProjectionMatrix();
        cameraHelper.update();

        // 在主视野中不要绘制cameraHelper
        cameraHelper.visible = false;

        // 更新第一个相机的控制器
        // controls.update();

        // 渲染第一个视野
        renderer.render(scene, camera);
      }

      // 渲染第二台摄像机 (view2)
      {
        const aspect = setScissorForElement(view2Elem);

        // 调整第二个相机的aspect
        camera2.aspect = aspect;
        camera2.updateProjectionMatrix();

        // 在第二台摄像机中绘制cameraHelper
        cameraHelper.visible = true;

        // 更新第二个相机的控制器
        controls2.update();

        // 渲染第二个视野
        renderer.render(scene, camera2);
      }

      // 旋转base（可选）
      baseObrit.rotation.y -= 0.002;

      // 继续动画循环
      requestAnimationFrame(render);
    }

    // 启动渲染循环
    requestAnimationFrame(render);

    // 监听窗口变化
    function handleResize() {
      // 渲染器会在render函数中自动调整大小
      // 这里不需要手动设置
    }

    window.addEventListener('resize', handleResize);

    // 清理函数
    return () => {
      window.removeEventListener('resize', handleResize);
      view1Elem.removeEventListener('click', handleMouseClick);
      view2Elem.removeEventListener('click', handleMouseClick);
      // controls.dispose();
      controls2.dispose();
      renderer.dispose();
      if (canvasRef.current && canvasRef.current.contains(renderer.domElement)) {
        canvasRef.current.removeChild(renderer.domElement);
      }
    };
  }, [])

  return (
    <>
      <div ref={canvasRef} id="c"></div>
      <div className="split">
        <div ref={view1Ref} id="view1" tabIndex="1"></div>
        <div ref={view2Ref} id="view2" tabIndex="2"></div>
      </div>
    </>
  )
}

export default App
